package com.lank.gateway.config.service.impl;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 郑海宾
 * @since 2020/7/23 上午10:57 星期四
 */

@Slf4j
@Component
public class CustomAuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {

    /**
     * 实现权限验证判断
     */
    @Override
    public Mono<AuthorizationDecision> check(Mono<Authentication> authenticationMono, AuthorizationContext authorizationContext) {
        ServerWebExchange exchange = authorizationContext.getExchange();
        //请求资源
        String requestPath = exchange.getRequest().getURI().getPath();
        return authenticationMono.map(auth -> new AuthorizationDecision(checkAuthorities(exchange, auth, requestPath))).defaultIfEmpty(new AuthorizationDecision(false));
    }

    /**
     * 权限校验
     */
    private boolean checkAuthorities(ServerWebExchange exchange, Authentication auth, String requestPath) {

        Jwt principal = (Jwt) auth.getPrincipal();
        String userName = (String) principal.getClaims().get("user_name");
        Object obj = principal.getClaims().get("urls");
        List<String> urls = Lists.newArrayList();
        if (obj instanceof ArrayList<?>) {
            for (Object o : (List<?>) obj) {
                urls.add((String) o);
            }
        }
        long count = urls.stream().filter(l -> l.equals(requestPath)).count();
        log.info("访问的URL是：{} 用户信息:{}", requestPath, userName);

//        return count > 0;
        return true;
    }

}
